﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace System.Erp.Runtime.Services
{
    /// <summary>
    /// 一个服务申请的键
    /// </summary>
    [Serializable]
    public sealed class CompositionServiceKey
    {
        /// <summary>
        /// 服务类型
        /// </summary>
        public readonly Type ServiceType;

        /// <summary>
        /// 服务的对象键
        /// </summary>
        public readonly TypeKey TypeKey;

        /// <summary>
        /// 返回类型的字符串描述
        /// </summary>
        /// <returns>此类型的字符串描述方法。</returns>
        public override string ToString()
        {
            return (this.TypeKey.IsGlobal ? "Global" : this.TypeKey.StringValue) + "." + ServiceType.Name;
        }

        /// <summary>
        /// 自定义的相等判断
        /// </summary>
        /// <param name="obj">要判断相等的对象</param>
        /// <returns>返回是否相等。</returns>
        public override bool Equals(object obj)
        {
            CompositionServiceKey other = obj as CompositionServiceKey;
            return (other == null) ? false : Equals(this, other);
        }

        /// <summary>
        /// 返回两个对象是否相等
        /// </summary>
        /// <param name="a">要判断的对象</param>
        /// <param name="b">要判断的对象</param>
        /// <returns>如果对象相等返回true，否则返回false</returns>
        public static bool Equals(CompositionServiceKey a, CompositionServiceKey b)
        {
            return (object.ReferenceEquals(a, b) ||
                ((!object.ReferenceEquals(a, null) && !object.ReferenceEquals(b, null)) &&
                 (a.TypeKey == b.TypeKey) && (a.ServiceType == b.ServiceType)));
        }

        /// <summary>
        /// 返回此对象的Hashcode，为类型字符串的hashcode.
        /// </summary>
        /// <returns>Hashcode的值。</returns>
        public override int GetHashCode()
        {
            return this.ServiceType.GetHashCode() ^ this.TypeKey.GetHashCode();
        }

        /// <summary>
        /// 返回两个对象是否相等
        /// </summary>
        /// <param name="a">要判断的对象</param>
        /// <param name="b">要判断的对象</param>
        /// <returns>如果对象相等返回true，否则返回false</returns>
        public static bool operator ==(CompositionServiceKey a, CompositionServiceKey b)
        {
            return Equals(a, b);
        }

        /// <summary>
        /// 返回两个类型对象是否不相等
        /// </summary>
        /// <param name="a">要判断的对象</param>
        /// <param name="b">要判断的对象</param>
        /// <returns>如果对象不相等返回true，否则返回false</returns>
        public static bool operator !=(CompositionServiceKey a, CompositionServiceKey b)
        {
            return !Equals(a, b);
        }

        /// <summary>
        /// 构造对象
        /// </summary>
        /// <param name="serviceType">申请的服务接口类型，不能为空</param>
        /// <param name="typeKey">对象的键。</param>
        public CompositionServiceKey(Type serviceType, TypeKey typeKey)
        {
            if (serviceType == null)
            {
                throw new ArgumentNullException("serviceType");
            }
            if (typeKey == null)
            {
                throw new ArgumentNullException("typeKey");
            }

            if (TypeKeyOnlyAttribute.IsTypeKeyOnly(serviceType))
            {
                if (typeKey.IsGlobal)
                {
                    throw new ApplicationException(string.Format("申请的服务{0}要求使用分类处理，必须提供TypeKey参数", serviceType));
                }
            }
            else if (!typeKey.IsGlobal)
            {
                throw new ApplicationException(string.Format("申请的服务{0}要求不使用分类处理，但现在的调用提供了TypeKey参数{1}", serviceType, typeKey));
            }

            this.ServiceType = serviceType;
            this.TypeKey = typeKey;
        }
    }
}
